-- 运营活动: 幸运购


--[[
{
    cmd_id = 1, -- 命令id，用于批量停止、删除活动 
    act_id = 57, -- 活动id (57 幸运购)
    act_name = "幸运购", -- 活动名称
    act_desc = "每次摇奖都可获取积分，消耗积分兑换奖励！", -- 活动描述
    beg_time = 1493262000,  -- 活动开始时间(unix timestamp)
    end_time = 1593267400,  -- 活动结束时间(unix timestamp)
    config = -- 配置数据
    {
        dailyItems = 
        {
            {type = 0, id = 842, count = 1, bind = 0,},  --第一天团购物品
            {type = 0, id = 852, count = 1, bind = 0,},
            {type = 0, id = 862, count = 1, bind = 0,},
            {type = 0, id = 872, count = 1, bind = 0,},
            {type = 0, id = 1161, count = 1, bind = 0,},
            {type = 0, id = 1162, count = 1, bind = 0,},
            {type = 0, id = 1163, count = 1, bind = 0,},
            {type = 0, id = 1171, count = 1, bind = 0,},
            {type = 0, id = 1172, count = 1, bind = 0,},
            {type = 0, id = 1173, count = 1, bind = 0,},
            {type = 0, id = 1181, count = 1, bind = 0,},
            {type = 0, id = 1182, count = 1, bind = 0,},
            {type = 0, id = 1183, count = 1, bind = 0,},
            {type = 0, id = 1189, count = 1, bind = 0,},
            {type = 0, id = 841, count = 1, bind = 0,},
            {type = 0, id = 851, count = 1, bind = 0,},
            {type = 0, id = 861, count = 1, bind = 0,},
            {type = 0, id = 871, count = 1, bind = 0,},
        },
        dailySpecialItems = 
        {
            {   --第一天特殊奖励
                {type = 0, id = 842, count = 1, bind = 0,},
                {type = 0, id = 852, count = 1, bind = 0,},
                {type = 0, id = 862, count = 1, bind = 0,},
            },
        },
        buyCost = 30, --购买消耗元宝
        AwardTime = 75600, --当天第几秒的时候开奖
        LastBuyCount = 200,     --开奖最低全服购买次数
        singleBuyTime = {18,0,0}, --个人购买次数限制时间
        singleBuyCount = 150,     --限制时间内最多购买次数
    },
}
]]

-- 检查配置是否正确，正确则返回 0，否则返回错误码
function oper_act_57_check_cfg(cfg)
    if cfg == nil then return 20 end
    
    local config = cfg.config
    if config == nil then return 21 end
    
    if config.dailySpecialItems == nil then return 23 end
    if type(config.dailySpecialItems) ~= "table" then return 24 end
    
    if not oper_act_check_one_award_cfg(config.dailySpecialItems) then
        return 22
    end 

    if config.dailyItems == nil then return 25 end
    if type(config.dailyItems) ~= "table" then return 26 end
    for idx = 1, #config.dailyItems do
        local dayRewards2 = config.dailyItems[idx]
        if dayRewards2 == nil then return 27 end
        if type(dayRewards2) ~= "table" then return 28 end
        if not oper_act_check_one_award_cfg(dayRewards2) then
            return 29
        end 
    end

    if not config.singleBuyTime then
        return 30
    end
    if not config.singleBuyCount then
        return 31
    end
    return 0
end

-- 安装活动，成功则返回 0，否则返回错误码
function oper_act_57_setup(cfg) 
    return 0
end

-- 卸载活动
function oper_act_57_unsetup(cfg)   
end

-- 活动开始
function oper_act_57_start(cfg)
    local ssVar = System.getStaticVar()
    ssVar.oper_act_57_start = 1
    ssVar.oper_act_57_cmd = cfg.cmd_id
    ssVar.oper_act_57_act = cfg.act_id

    if not cfg then return end
    local config = cfg.config
    if not config then return end

    local data = gRankMgr_GetValueByIndx(0, RANK_DEFINE_OPERATION_57, 1)

    local needClearState = true

    local crossDayState = false

    local needGiveAwards = false

    local needAddEvent = false

    local time = System.getSystemTime()

    local lastTime = System.getCurrMiniTime() - System.getToday()

    if data then
        local myData = BaseFuc_unserialize(data)
        if lastTime >= config.AwardTime and myData and not myData.getAward then
            needGiveAwards = true
        elseif lastTime < config.AwardTime then
            needAddEvent = true
        end
        if myData and myData.cmd_id and myData.cmd_id == cfg.cmd_id and myData.act_id and myData.act_id == cfg.act_id and
            myData.time and cfg.beg_time <= myData.time and  cfg.end_time > myData.time then
            needClearState = false
            if myData and myData.mySelfTime and not System.isUnixTimeSameDay(myData.mySelfTime, time) then
                crossDayState = true
                if not myData.getAward then
                    needGiveAwards = true
                end
            end
        end
    end

    if needGiveAwards then
        oper_act_57_give_award()
    end

    if needClearState or crossDayState then
        gRankMgr_Clear(RANK_DEFINE_OPERATION_57)
    end

    if needClearState or crossDayState or needAddEvent then
        local awardTime = config.AwardTime - lastTime
        local timerH = System.getTimeCall(System.getGlobalNpc(), "oper_act_57_give_award")
        if timerH then
            System.unregisterTimeCall(timerH)
        end
        System.registerTimeCall(System.getGlobalNpc(), "oper_act_57_give_award", NULL, awardTime, false)
        --Actor.unregScriptCallback( System.getGlobalNpc(), "oper_act_57_give_award") 
        --Actor.regScriptTimer(System.getGlobalNpc(), 0, awardTime * 1000, awardTime * 1000, 1, "oper_act_57_give_award") 
    end

    if needClearState then
        ssVar.oper_act_57_buy_count = 0
        ssVar.oper_act_57_day_index = 1
        ssVar.oper_act_57_day_round_index = 1
        ssVar.oper_act_57_log = nil
    end

    if crossDayState then
        ssVar.oper_act_57_buy_count = 0
        ssVar.oper_act_57_day_round_index = 1
        if not ssVar.oper_act_57_day_index then
            ssVar.oper_act_57_day_index = 1
        end
        ssVar.oper_act_57_day_index = ssVar.oper_act_57_day_index + 1
        ssVar.oper_act_57_log = nil
    end

end

-- 活动结束
function oper_act_57_end(cfg)
    local ssVar = System.getStaticVar()
    ssVar.oper_act_57_start = nil
    ssVar.oper_act_57_cmd = nil
    ssVar.oper_act_57_act = nil

    if not cfg then return end
    local config = cfg.config
    if not config then return end

    local timerH = System.getTimeCall(System.getGlobalNpc(), "oper_act_57_give_award")
    if timerH then
        System.unregisterTimeCall(timerH)
    end
end

-- 打包数据
function oper_act_57_packet_data(sysarg, cfg)
    if not cfg then return end
    local config = cfg.config
    if not config then return end
    
    local ssVar = System.getStaticVar()
    
    local actorid = Actor.getActorId(sysarg)
    local data = gRankMgr_GetValueById(actorid, RANK_DEFINE_OPERATION_57, 1)

    local myData = BaseFuc_unserialize(data)
    

    if not myData then
        myData = {}
    end

    if not myData.buyCount then
        myData.buyCount = 0
    end

    if not ssVar.oper_act_57_day_index then
        ssVar.oper_act_57_day_index = 1
    end

    if not ssVar.oper_act_57_buy_count then
        ssVar.oper_act_57_buy_count = 0
    end
    if not ssVar.oper_act_57_log then
        ssVar.oper_act_57_log = {}
    end

    if not ssVar.oper_act_57_day_round_index then
        ssVar.oper_act_57_day_round_index = 1
    end
    local npack = oper_act_alloc_init_data_packet(sysarg, cfg.cmd_id, cfg.act_id)
    if (npack == nil) then
        return
    end
    --print("lastCount ="..lastCount)

    DataPack.writeByte(npack, ssVar.oper_act_57_day_index)
    DataPack.writeInt(npack, ssVar.oper_act_57_buy_count)
    DataPack.writeInt(npack, myData.buyCount)
    DataPack.writeByte(npack, ssVar.oper_act_57_day_round_index)
    for i=1, ssVar.oper_act_57_day_round_index do
        local awardData = ssVar.oper_act_57_log[i] or {}
        DataPack.writeByte(npack, i)
        DataPack.writeString(npack, awardData.name or "")
        DataPack.writeInt(npack, awardData.time or 0)
    end
    DataPack.flush(npack) 
end

-- 操作，返回操作结果，0为成功
function oper_act_57_do(sysarg, cfg, clientPkt)
    if cfg == nil then return end
    
    if cfg.state == nil or cfg.state ~= 1 then -- 不在活动中
        Actor.sendTipmsg(sysarg,Lang.ScriptTips.Operation001, ttFlyTip)
        return
    end
    
    local config = cfg.config
    if config == nil then -- 参数错误
        print("error, oper_act_57_do cfg.config confg error")
        return
    end

    local time = System.getSystemTime()
    local lastTime = System.getCurrMiniTime() - System.getToday()
    if lastTime >= config.AwardTime then
        Actor.sendTipmsg(sysarg,Lang.ScriptTips.Operation150, ttFlyTip)
        return 
    end

    local actorid = Actor.getActorId(sysarg)
    local data = gRankMgr_GetValueById(actorid, RANK_DEFINE_OPERATION_57, 1)

    local myData = BaseFuc_unserialize(data)
    

    if not myData then
        myData = {}
    end

    if myData.getAward and myData.getAward == 1 then
        Actor.sendTipmsg(sysarg,Lang.ScriptTips.Operation173, ttFlyTip)
        return
    end

    if not myData.buyCount then
        myData.buyCount = 0
    end
    local ssVar = System.getStaticVar()
    if not ssVar.oper_act_57_buy_count then
        ssVar.oper_act_57_buy_count = 0
    end

    if not ssVar.oper_act_57_day_index then
        ssVar.oper_act_57_day_index = 1
    end

    if System.isInTimeRange(0,0,0, unpack(config.singleBuyTime)) then
        if myData.buyCount >= config.singleBuyCount then
            local hour = config.singleBuyTime[1]
            local min = tostring(config.singleBuyTime[2])
            if string.len(min) <= 1 then
                min = min .."0"
            end
            Actor.sendTipmsg(sysarg, string.format(Lang.ScriptTips.Operation254, hour, min,config.singleBuyCount) , ttFlyTip)
            return
        end
    end

    local dailyRewards = config.dailyItems[ssVar.oper_act_57_day_index]
    if not Awards.CheckBagGridCount(sysarg, dailyRewards) then
        return
    end

    local costMoney = config.buyCost[ssVar.oper_act_57_day_index]
    if not costMoney then
        costMoney = config.buyCost[#config.buyCost]
        ssVar.oper_act_57_day_index = #config.buyCost
    end



    if Actor.getMoneyCount(sysarg, mtYuanbao) < costMoney then
        Actor.sendItemLack( sysarg, qatYuanbao, 0, costMoney )
        return
    end

    if not Actor.delMoney( sysarg,mtYuanbao,costMoney,LogIds.OperationLogId057,Lang.LogTips.Operation057) then
        return
    end

    myData.buyCount = myData.buyCount + 1
    ssVar.oper_act_57_buy_count = ssVar.oper_act_57_buy_count + 1

    if not myData.cmd_id then
        myData.cmd_id = cfg.cmd_id
        myData.act_id = cfg.act_id
        myData.time = time
    end

    if not myData.sex then
        myData.sex = Actor.getIntProperty(sysarg, PROP_ACTOR_SEX)
        myData.vocation = Actor.getIntProperty(sysarg, PROP_ACTOR_VOCATION)
    end

    myData.mySelfTime = time

    local newData = BaseFuc_serialize(myData)
    gRankMgr_SetRankEx(actorid, RANK_DEFINE_OPERATION_57, 1, newData)

    local npack = oper_act_alloc_do_result_packet(sysarg, cfg.cmd_id, cfg.act_id, 0)
    if not npack then return end

    DataPack.writeByte(npack, ssVar.oper_act_57_day_index)
    DataPack.writeInt(npack, ssVar.oper_act_57_buy_count)
    DataPack.writeInt(npack, myData.buyCount)

    DataPack.flush(npack)

    
    if not dailyRewards then
        dailyRewards = config.dailyItems[#config.dailyItems]
    end

    Awards.Give(sysarg, dailyRewards, LogIds.OperationLogId057, Lang.LogTips.Operation057)     
 
    if ssVar.oper_act_57_buy_count >= config.LastBuyCount then
        oper_act_57_give_award()
        oper_act_57_packet_data(sysarg, cfg)
    end
end


-- 跨天
function oper_act_57_new_day_arrive(act_id) 
    local ssVar = System.getStaticVar()
    if not ssVar.oper_act_57_start then
        return
    end
    if not ssVar.oper_act_57_cmd then
        return
    end
    if not ssVar.oper_act_57_act then
        return
    end
    local cfg = get_oper_act_cfg(ssVar.oper_act_57_cmd, ssVar.oper_act_57_act)
    if not cfg then
        return
    end
    local config = cfg.config
    if not config then return end

    gRankMgr_Clear(RANK_DEFINE_OPERATION_57)
    local lastTime = System.getCurrMiniTime() - System.getToday()
    local awardTime = config.AwardTime - lastTime

    local timerH = System.getTimeCall(System.getGlobalNpc(), "oper_act_57_give_award")
    if timerH then
        System.unregisterTimeCall(timerH)
    end
    System.registerTimeCall(System.getGlobalNpc(), "oper_act_57_give_award", NULL, awardTime, false)

    --Actor.unregScriptCallback( System.getGlobalNpc(), "oper_act_57_give_award") 
    --Actor.regScriptTimer(System.getGlobalNpc(), 0, awardTime * 1000, awardTime * 1000, 1, "oper_act_57_give_award")    

    ssVar.oper_act_57_buy_count = 0
    ssVar.oper_act_57_day_round_index = 1
    if not ssVar.oper_act_57_day_index then
        ssVar.oper_act_57_day_index = 1
    end
    ssVar.oper_act_57_day_index = ssVar.oper_act_57_day_index + 1
    ssVar.oper_act_57_log = nil
end



function oper_act_57_give_award()
    local timerH = System.getTimeCall(System.getGlobalNpc(), "oper_act_57_give_award")
    if timerH then
        System.unregisterTimeCall(timerH)
    end

    local ssVar = System.getStaticVar()
    if not ssVar.oper_act_57_start then
        return
    end
    if not ssVar.oper_act_57_cmd then
        return
    end
    if not ssVar.oper_act_57_act then
        return
    end
    if not ssVar.oper_act_57_log then
        ssVar.oper_act_57_log = {}
    end
    local cfg = get_oper_act_cfg(ssVar.oper_act_57_cmd, ssVar.oper_act_57_act)
    if not cfg then
        return
    end
    local config = cfg.config
    if not config then return end

    if not ssVar.oper_act_57_buy_count then
        ssVar.oper_act_57_buy_count = 0
    end

    if not ssVar.oper_act_57_day_index then
        ssVar.oper_act_57_day_index = 1
    end

    if not ssVar.oper_act_57_day_round_index then
        ssVar.oper_act_57_day_round_index = 1
    end

    local costMoney = config.buyCost[ssVar.oper_act_57_day_index]
    if not costMoney then
        costMoney = config.buyCost[#config.buyCost]
        ssVar.oper_act_57_day_index = #config.buyCost
    end

    local dailySpecialRewards = config.dailySpecialItems[ssVar.oper_act_57_day_index]
    if not dailySpecialRewards then
        dailySpecialRewards = config.dailySpecialItems[#config.dailySpecialItems]
    end

    local time = System.getSystemTime()

    local giveAward = true
  

    local specialAward = true
    local randNum = System.getRandomNumber(ssVar.oper_act_57_buy_count) + 1
    local weight = 0
    local rankPtr = Ranking.getRanking(RankList[RANK_DEFINE_OPERATION_57].strName)
    local rankCount = Ranking.getRankItemCount(rankPtr)
    for idx = 1, rankCount do
        local item = Ranking.getItemFromIndex(rankPtr, idx-1)
        if item then
            local actorid = tonumber(Ranking.getId(item))
            local data = Ranking.getSub(item, 1)
            local dataTable
            if not data or data == "" then
                dataTable = {}
            else
                dataTable = BaseFuc_unserialize(data)
            end
            if not dataTable then
                dataTable = {}
            end
            if not dataTable.buyCount then
                dataTable.buyCount = 0
            end
            if not dataTable.getAward and dataTable.buyCount > 0 then
                if giveAward then
                    weight = weight + dataTable.buyCount
                    if weight >= randNum and specialAward then
                        specialAward = false
                        local title = Lang.ScriptTips.Operation153
                        local content = Lang.ScriptTips.Operation154

                        Awards.GiveToMailById(actorid, {dailySpecialRewards}, title, content, LogIds.OperationLogId057, Lang.LogTips.Operation057, dataTable.vocation, dataTable.sex)
                        ssVar.oper_act_57_log[ssVar.oper_act_57_day_round_index] = {name = Ranking.getSub(item, 0), time = System.getSystemTime()}
                    end

                -- else
                --     local myGetGoldNum = dataTable.buyCount * costMoney
                --     local title = Lang.ScriptTips.Operation157
                --     local content = Lang.ScriptTips.Operation158
                --     local moneyRewards = {{type = 10, id = 0, count = myGetGoldNum}}
                --     Awards.GiveToMailById(actorid, moneyRewards, title, content, LogIds.OperationLogId057, Lang.LogTips.Operation057, dataTable.vocation, dataTable.sex)
                    
                end
            end

            dataTable.getAward = 1
            if not dataTable.cmd_id then
                dataTable.cmd_id = cfg.cmd_id
                dataTable.act_id = cfg.act_id
                dataTable.time = time
            end

            dataTable.mySelfTime = time
            local newData = BaseFuc_serialize(dataTable)
            gRankMgr_SetRankEx(actorid, RANK_DEFINE_OPERATION_57, 1, newData)
        end
    end
    local lastTime = System.getCurrMiniTime() - System.getToday()
    --新增，满人时，awardTime之前重开一轮新的
    if lastTime < config.AwardTime and config.LastBuyCount <= ssVar.oper_act_57_buy_count  then
        gRankMgr_Clear(RANK_DEFINE_OPERATION_57)
        local awardTime = config.AwardTime - lastTime
        local timerH = System.getTimeCall(System.getGlobalNpc(), "oper_act_57_give_award")
        if timerH then
           System.unregisterTimeCall(timerH)
        end
        System.registerTimeCall(System.getGlobalNpc(), "oper_act_57_give_award", NULL, awardTime, false)
        ssVar.oper_act_57_buy_count = 0
        ssVar.oper_act_57_day_round_index = ssVar.oper_act_57_day_round_index + 1
    end
   
end

